#ifndef __COMPONENT_VITAL_STATS_H__
#define __COMPONENT_VITAL_STATS_H__

#include <map>
#include <mutex>
#include "Component.hpp"
#include "Engine/MathUtils.hpp"

using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    struct IInventory;
    struct ComponentPlayer;
    struct ComponentVitalStats : public Component
    {
        // 饱腹
        float food;
        // 耐力
        float stamina;
        // 睡眠
        float sleep;
        // 身体温度
        float temperature;
        // 身体湿度
        float wetness;
        // 环境温度
        float environmentTemperature;
        // 环境温度通量
        float environmentTemperatureFlux;

        // 应用密度调节
        float densityModifierApplied;

        ComponentPlayer *componentPlayer;

        std::map<int32_t, float> satiationMap;
        std::mutex satiationMapMutex;

        inline void setFood(float value);
        inline void setStamina(float value);
        inline void setSleep(float value);
        inline void setTemperature(float value);
        inline void setWetness(float value);
        inline void makeSleepy(float sleepValue);
        
        bool eat(IInventory *inventory, int32_t slotIndex, int32_t value);
        void applyDensityModifier(float modifier);

        virtual void update(float dt) override;
        virtual const std::string &getName() const override;
        static const std::string &GetName();
        virtual void load(const nlohmann::json &jsonData) override;
        virtual void save(nlohmann::json &jsonData) override;
        virtual void saveToMsgJson(nlohmann::json &jsonData) override;
    };

    inline void ComponentVitalStats::setFood(float value)
    {
        food = MathUtils::Saturate(value);
    }
    inline void ComponentVitalStats::setStamina(float value)
    {
        stamina = MathUtils::Saturate(value);
    }
    inline void ComponentVitalStats::setSleep(float value)
    {
        sleep = MathUtils::Saturate(value);
    }
    inline void ComponentVitalStats::setTemperature(float value)
    {
        temperature = MathUtils::Clamp(value, 0.0f, 24.0f);
    }
    inline void ComponentVitalStats::setWetness(float value)
    {
        wetness = MathUtils::Saturate(value);
    }
    inline void ComponentVitalStats::makeSleepy(float sleepValue)
    {
        sleep = MathUtils::Min<float>(sleep, sleepValue);
    }

} // namespace PocketSurvival

#endif
